﻿#include "GraphicsView.h"
#include <GraphicsScene.h>
#include <GraphicsUtil.h>
#include <QWheelEvent>
#include <QGraphicsProxyWidget>

GraphicsView::GraphicsView(QWidget* parent)
	: QGraphicsView(parent)
{
	setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
	setCacheMode(QGraphicsView::CacheBackground);
	setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
	setMouseTracking(true);//跟踪鼠标位置
	setStyleSheet("border:none");
	//在鼠标点击处进行放大缩小
	//注：起作用的前提是垂直和水平方向场景比视图大，可以简单理解为有水平和垂直滚动条
	//setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
	//setResizeAnchor(QGraphicsView::AnchorUnderMouse);
}

GraphicsView::~GraphicsView()
{

}

void GraphicsView::init()
{
	createMinimap();
}

void GraphicsView::wheelEvent(QWheelEvent* event)
{
#if 1
	const qreal itemScale = getItemScale();
	if (event->angleDelta().y() > 0 && itemScale <= 2.0) {
		qreal newScale = qMin(2.0, itemScale + 0.08);
		setItemScale(newScale);
	}
	if (event->angleDelta().y() < 0 && itemScale >= 0.1) {
		qreal newScale = qMax(0.1, itemScale - 0.08);
		setItemScale(newScale);
	}
#else
	// 获取当前鼠标所在的view坐标
	QPoint preViewPos = mapFromGlobal(QCursor::pos());
	// 获取当前鼠标相对于scene的位置
	QPointF prevScenePos = mapToScene(preViewPos);
	//if (event->modifiers() == Qt::CTRL)
	{// 按住ctrl键 可以放大缩小
		GraphicsScene* graphicsScene = getScene();
		if (!graphicsScene)
			return;
		const qreal viewScale = getViewScale();
		GraphicsBaseItem* baseItem = graphicsScene->getCenterItem();
		if (baseItem) {
			centerOn(baseItem);
		}

		if (event->angleDelta().y() > 0 && viewScale >= 50) {
			//最大放大到原始图像的50倍
			return;
		}
		else if (event->angleDelta().y() < 0 && viewScale <= 0.01) {
			// 图像缩小到自适应大小之后就不继续缩小
			return;
		}
		else {
			int wheelDeltaVal = event->angleDelta().y();
			qreal scaleFactor = 1.15;
			if (wheelDeltaVal > 0) {
				// 向上滚动，放大
				scale(scaleFactor, scaleFactor);
			}
			else {
				// 向下滚动，缩小
				scale(1.0 / scaleFactor, 1.0 / scaleFactor);
			}
			// qDebug() << "缩放倍数:" << viewScale;
			emit sigViewScaleChanged();
		}
	}
#endif
	event->ignore();
}

void GraphicsView::resizeEvent(QResizeEvent* event)
{
	updateMinimapPosition();
	QGraphicsView::resizeEvent(event);
}

void GraphicsView::drawForeground(QPainter* painter, const QRectF& rect)
{
	painter->save();
	// 视图在场景中坐标
	GraphicsScene* pScene = getScene();
	GraphicsBaseItem* centerItem = pScene->getCenterItem();
	if (pScene && m_originImageVisable && centerItem) {
		QRect rect(QPoint(0, 0), size());
		QRectF visabledRect = mapToScene(rect).boundingRect();
		painter->setBrush(QColor(26, 26, 26));
		painter->drawRect(visabledRect.toRect());
		// 显示原图
		QImage originImage = centerItem->getItemData().getOriginImage();
		if (!originImage.isNull()) {
			const qreal imageRatio = (qreal)originImage.width() / (qreal)originImage.height();
			QSizeF visableSize = visabledRect.size() * 0.9;
			const QSizeF keepSize = GraphicsUtil::getKeepRatioSize(visableSize.width(), visableSize.height(), imageRatio);
			QImage image = originImage.scaled(keepSize.toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
			QRectF imageRect(0, 0, image.width(), image.height());
			imageRect.moveCenter(visabledRect.center());
			painter->drawImage(imageRect.topLeft(), image);
		}
	}
	painter->restore();
	QGraphicsView::drawForeground(painter, rect);
}

void GraphicsView::updateMinimapPosition()
{
	if (!m_minimapContainter)
		return;
	const int w = m_minimapContainter->width();
	const int h = m_minimapContainter->height();
	const int padding = 20;
	m_minimapContainter->move(width() - w - padding, height() - h - padding);
}

void GraphicsView::createMinimap()
{
	QWidget* graphicsViewport = viewport();
	m_minimapContainter = new MinimapContainterWidget(graphicsViewport);
	m_minimapContainter->setScene(getScene());

	connect(this, &GraphicsView::sigViewScaleChanged, [=] {
		m_minimapContainter->onViewScaleChanged();
		updateMinimapPosition();
		});
}

GraphicsScene* GraphicsView::getScene()
{
	return dynamic_cast<GraphicsScene*>(scene());;
}


void GraphicsView::setOriginImageVisable(bool isVisable)
{
	m_originImageVisable = isVisable;
	if (isVisable) {
		m_oldItemScale = getViewScale();
		QTransform transform;
		transform.scale(1.0, 1.0);
		setTransform(transform);
	}
	else {
		scale(m_oldItemScale, m_oldItemScale);
	}
	viewport()->update();
}

qreal GraphicsView::getViewScale()
{
	return  this->transform().m11();
}

qreal GraphicsView::getItemScale()
{
	GraphicsScene* scene = getScene();
	if (!scene)
		return getViewScale();

	GraphicsBaseItem* centerItem = scene->getCenterItem();
	if (!centerItem)
		return getViewScale();

	// 获取当前item在view中的大小
	const QRectF scaleRect = centerItem->getItemData().getScaleRect();
	const QRectF scaleViewRect = mapFromScene(scaleRect).boundingRect();
	// 获取当前item的默认尺寸
	const QSize size = centerItem->getItemData().getDefaultSize();
	// 计算缩放比列
	const qreal scaleFactor = scaleViewRect.width() / (qreal)size.width();
	return scaleFactor;
}

void GraphicsView::setItemScale(qreal itemScale)
{
	// 根据尺寸，计算view的缩放系数
	GraphicsScene* scene = getScene();
	if (!scene)
		return;

	GraphicsBaseItem* centerItem = scene->getCenterItem();
	if (!centerItem)
		return;

	// 获取当前item在view中的大小
	const QRectF scaleRect = centerItem->getItemData().getScaleRect();
	const QRectF scaleViewRect = mapFromScene(scaleRect).boundingRect();

	// 计算需要在view中显示的尺寸
	QSize imageViewSize = centerItem->getItemData().getDefaultSize() * itemScale;

	// 计算view的缩放比例
	const qreal scaleFactor = imageViewSize.width() / scaleViewRect.width();
	scale(scaleFactor, scaleFactor);
	centerOn(centerItem);
	emit sigViewScaleChanged();
}

void GraphicsView::setMinimapVisable(bool visabled)
{
	m_minimapContainter->setMinimapVisable(visabled);
}

void GraphicsView::autoFitSize()
{
	GraphicsScene* grphicsScene = getScene();
	assert(grphicsScene);
	// 视图在场景中的位置
	GraphicsBaseItem* centerItem = grphicsScene->getCenterItem();
	if (!centerItem)
		return;
	const QRectF itemSceneRect = centerItem->getItemData().getScaleRect();
	// item在视图中的尺寸
	const QRectF itemInViewRect = mapFromScene(itemSceneRect).boundingRect();
	const qreal factor = itemSceneRect.width() / itemSceneRect.height();
	const int w = width();
	const int h = height();
	const QSizeF ratioSize = GraphicsUtil::getKeepRatioSize(w * 0.9, h * 0.9, factor, false);
	const qreal newScale = ratioSize.width() / itemSceneRect.width();

	QTransform transform;
	transform.scale(newScale, newScale);
	setTransform(transform);
	centerOn(centerItem);
	emit sigViewScaleChanged();
}

